package xworker.lang.util.refactor;

import org.xmeta.Thing;
import org.xmeta.ThingManager;
import org.xmeta.World;
import org.xmeta.codes.DmlThingCoder;
import xworker.lang.util.FileUtils;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 重构模型的工具，但不保证运行完全正确，因此只是简单的判断字符串中含有值，则替换。
 * 因此重构时请小心。
 */
public class ThingRefatorUtils {
    static Map<String, String> javaMap = new HashMap<>();
    static Map<String, String> thingMap = new HashMap<>();

    static{
        javaMap.put("xworker.core.security.DefaultSecurityHandler", "xworker.lang.security.DefaultSecurityHandler");
        javaMap.put("xworker.core.security.PermissionActionHandler", "xworker.lang.security.PermissionActionHandler");
        thingMap.put("xworker.core.security.DefaultSecirutyHandlerImpl", "xworker.lang.security.DefaultSecirutyHandlerImpl");
        thingMap.put("xworker.core.security.DefaultSecurityHandler", "xworker.lang.security.DefaultSecurityHandler");
        thingMap.put("xworker.core.security.DefaultSecurityManager", "xworker.lang.security.DefaultSecurityManager");
        thingMap.put("xworker.core.security.editors.ActionSelector", "xworker.lang.security.editors.ActionSelector");
        thingMap.put("xworker.core.security.PermissionActionHandler", "xworker.lang.security.PermissionActionHandler");
        thingMap.put("xworker.core.security.PermissionActionHandlers", "xworker.lang.security.PermissionActionHandlers");
        thingMap.put("xworker.core.security.PermissionIndex", "xworker.lang.security.PermissionIndex");
        thingMap.put("xworker.core.security.Permissions", "xworker.lang.security.Permissions");
        thingMap.put("xworker.core.security.PermissionViewer", "xworker.lang.security.PermissionViewer");
        thingMap.put("xworker.core.security.Security", "xworker.lang.security.Security");
        thingMap.put("xworker.core.security.SecurityActions", "xworker.lang.security.SecurityActions");
        thingMap.put("xworker.core.security.SecurityHandler", "xworker.lang.security.SecurityHandler");
        thingMap.put("xworker.core.security.SecurityHandlers", "xworker.lang.security.SecurityHandlers");
        thingMap.put("xworker.core.security.SecurityHandlerViewer", "xworker.lang.security.SecurityHandlerViewer");
        thingMap.put("xworker.core.security.SecurityManager", "xworker.lang.security.SecurityManager");
        thingMap.put("xworker.core.security.SessionSecurityHandler", "xworker.lang.security.SessionSecurityHandler");
        thingMap.put("xworker.core.security.SimpleSecurityHandler", "xworker.lang.security.SimpleSecurityHandler");
        thingMap.put("xworker.core.security.swt.SecurityManager", "xworker.lang.security.swt.SecurityManager");
        thingMap.put("xworker.core.security.WebTextSecurityHandler", "xworker.lang.security.WebTextSecurityHandler");


    }

    public static void main(String[] args){
        try{
            World world = World.getInstance();
            world.init("./xworker_explorer/xworker/");

            initThingManagers();

            //----------------------------step1--------------------------------
            //当类的包名发生变化时，通过该方法打印注册
            /*printChangedJava(
                    new File("d:\\git\\xworker\\xworker_core\\src\\main\\java\\xworker\\core\\security"),
                    "xworker.core.security",
                    "lang.security");*/
            //当模型的包名发生变化时，通过该方法打印注册`
            /*printChangedThing(
                    new File("d:\\git\\xworker\\xworker_core\\src\\main\\resources\\xworker\\core\\security"),
                    "xworker.core.security",
                    "lang.security");*/

            //----------------------------step2--------------------------------
            //执行修改
            modifyALlThings();
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    public static boolean changeThing(Thing thing){
        boolean changed = false;
        for(String name : thing.getAttributes().keySet()){
            String value = thing.getString(name);
            if(value != null){
                String oldValue = value;
                boolean attrChanged = false;
                for(String key : javaMap.keySet()){
                    if(value.contains(key)){

                        String path = javaMap.get(key);
                        if(!key.equals(path)) {
                            attrChanged = true;
                            System.out.println(thing.getMetadata().getPath() + "#" + name + ": " + key + " > " + path);
                            value = value.replaceAll(key, path);
                        }
                    }
                }

                for(String key : thingMap.keySet()){
                    if(value.contains(key)){

                        String path = thingMap.get(key);
                        if(!key.equals(path)) {
                            attrChanged = true;
                            System.out.println(thing.getMetadata().getPath() + "#" + name + ": " + key + " > " + path);
                            value = value.replaceAll(key, path);
                        }
                    }
                }

                if(attrChanged){
                    System.out.println("   changed: \n    " + oldValue + " \n    " + value);

                    thing.put(name, value);
                    changed = attrChanged;
                }
            }
        }

        for(Thing child : thing.getChilds()){
            if(changeThing(child)){
                changed = true;
            }
        }

        return changed;
    }

    public static void printChangedJava(File rootDir, String srcPackage, String destPackage){
        for(File file : FileUtils.listFiles(rootDir)){
            String name = file.getName();
            String spackage = srcPackage;
            if(spackage == null){
                if(name.equalsIgnoreCase(destPackage)) {
                    continue;
                }else{
                    spackage = "xworker";
                }
            }

            if(file.isDirectory()){
                printChangedJava(file, spackage + "." + name, destPackage + "." + name);
            }else if(name.endsWith(".java")){
                name = file.getName();
                int index = name.lastIndexOf(".");
                name = name.substring(0, index);
                System.out.println("        javaMap.put(\"" + spackage + "." + name + "\", \"xworker." + destPackage + "." + name + "\");");
            }
        }
    }

    public static void printChangedThing(File rootDir, String srcPackage, String destPackage){
        for(File file : FileUtils.listFiles(rootDir)){
            String name = file.getName();
            String spackage = srcPackage;
            if(srcPackage == null){
                if(name.equals(destPackage)) {
                    continue;
                }else{
                    spackage = "xworker";
                }
            }

            if(file.isDirectory()){
                printChangedThing(file,   spackage + "." + name, destPackage + "." + name);
            }else if(name.endsWith(".xer.txt")){
                name = file.getName();
                name = name.substring(0, name.length() - 8);
                System.out.println("        thingMap.put(\"" + spackage + "." + name + "\", \"xworker." + destPackage + "." + name + "\");");
            }else if(name.endsWith(".dml") || name.endsWith(".xer") || name.endsWith(".dmw")){
                name = file.getName();
                name = name.substring(0, name.length() - 4);
                System.out.println("        thingMap.put(\"" + spackage + "." + name + "\", \"xworker." + destPackage + "." + name + "\");");
            }
        }
    }

    private static void initThingManagers() throws IOException {
        World world = World.getInstance();

        File rootDir = new File(".");
        File[] children = rootDir.listFiles();
        if(children != null) {
            for (File dir : children) {
                File resources = new File(dir, "src/main/resources");
                if (resources.exists()) {
                    world.addFileThingManager(dir.getName(), resources, false, true);
                }
            }
        }
    }

    private static void modifyALlThings(){
        World world = World.getInstance();

        for(ThingManager thingManager : world.getThingManagers()){
            System.out.println("ThingManager: " + thingManager.getName());
            Iterator<Thing> iterator = thingManager.iterator(null, true);
            while(iterator.hasNext()){
                Thing thing = iterator.next();
                //System.out.println("check thing: " + thing.getMetadata().getPath());
                if(changeThing(thing)){
                    thing.save();
                }
            }
        }
    }

}
